package dnssec

import (
	"context"
	"fmt"
	"strings"

	googledns "dns-tools/pkg/dns"

	"github.com/miekg/dns"
)

// Detector DNSSEC 状态检测器
type Detector struct {
	resolver *googledns.GoogleDNSResolver
}

// NewDetector 创建 DNSSEC 检测器
func NewDetector() *Detector {
	return &Detector{
		resolver: googledns.NewGoogleDNSResolver(),
	}
}

// DetectState 检测域名的 DNSSEC 状态
// domain: 要检测的域名
// qtype: 查询类型（如 dns.TypeA, dns.TypeCAA, dns.TypeTXT）
func (d *Detector) DetectState(ctx context.Context, domain string, qtype uint16) *googledns.DNSSECInfo {
	// 标准化域名
	domain = strings.TrimSuffix(domain, ".")
	domain = strings.ToLower(domain)

	// 1. 发送 DO=1, CD=0 查询（请求验证）
	respCD0, err0 := d.resolver.QueryWithDNSSEC(ctx, domain, qtype, true, false)

	// 2. 发送 DO=1, CD=1 查询（禁用验证，获取原始数据）
	respCD1, err1 := d.resolver.QueryWithDNSSEC(ctx, domain, qtype, true, true)

	// 3. 分析结果并判定状态
	return d.analyzeResponses(respCD0, err0, respCD1, err1)
}

// analyzeResponses 分析两次查询的响应，判定 DNSSEC 状态
func (d *Detector) analyzeResponses(
	respCD0 *dns.Msg, errCD0 error,
	respCD1 *dns.Msg, errCD1 error,
) *googledns.DNSSECInfo {
	info := &googledns.DNSSECInfo{
		DO: true,
	}

	// 情况1：两次查询都失败 → Indeterminate
	if errCD0 != nil && errCD1 != nil {
		info.CD = false
		info.State = googledns.DNSSECStateIndeterminate
		info.RiskLevel = googledns.DNSSECRiskDanger
		info.Rcode = "TIMEOUT"
		info.Message = "查询超时或网络错误"
		return info
	}

	// 情况2：CD=0 查询成功
	if respCD0 != nil && errCD0 == nil {
		ad, _, cd, tc := d.resolver.GetDNSSECFlags(respCD0)
		rcode := d.resolver.GetRcode(respCD0)

		info.CD = cd
		info.AD = ad
		info.TC = tc
		info.Rcode = rcode

		// 情况2.1：AD=1 → Secure
		if ad {
			info.State = googledns.DNSSECStateSecure
			info.RiskLevel = googledns.DNSSECRiskNone
			info.Message = "DNSSEC 验证通过"
			return info
		}

		// 情况2.2：SERVFAIL（可能是 Bogus）
		if rcode == "SERVFAIL" {
			// 对比 CD=1 查询
			if respCD1 != nil && errCD1 == nil {
				rcode1 := d.resolver.GetRcode(respCD1)
				// CD=0 SERVFAIL, CD=1 NOERROR/NXDOMAIN → Bogus
				if rcode1 == "NOERROR" || rcode1 == "NXDOMAIN" {
					info.State = googledns.DNSSECStateBogus
					info.RiskLevel = googledns.DNSSECRiskDanger
					info.Message = "DNSSEC 签名验证失败（Bogus）"
					return info
				}
			}

			// 无法判定，可能是服务器问题
			info.State = googledns.DNSSECStateIndeterminate
			info.RiskLevel = googledns.DNSSECRiskDanger
			info.Message = "服务器错误（SERVFAIL）"
			return info
		}

		// 情况2.3：AD=0, Rcode=NOERROR/NXDOMAIN → 可能是 Insecure
		// 需要进一步检查是否有 DS 记录来判定
		if rcode == "NOERROR" || rcode == "NXDOMAIN" {
			// NXDOMAIN 表示域名不存在，且没有 DNSSEC 签名的否定应答
			if rcode == "NXDOMAIN" {
				info.State = googledns.DNSSECStateInsecure
				info.RiskLevel = googledns.DNSSECRiskWarning
				info.Message = "域名不存在（NXDOMAIN）"
				return info
			}

			// NOERROR 情况：检查是否有 DNSSEC 记录
			hasDNSSEC := d.resolver.HasDNSSECRecords(respCD0)
			if !hasDNSSEC {
				// 没有 DNSSEC 记录 → Insecure
				info.State = googledns.DNSSECStateInsecure
				info.RiskLevel = googledns.DNSSECRiskWarning
				info.Message = "未启用 DNSSEC 签名"
				return info
			}

			// 有 DNSSEC 记录但 AD=0 → 可能是验证问题
			info.State = googledns.DNSSECStateIndeterminate
			info.RiskLevel = googledns.DNSSECRiskDanger
			info.Message = "DNSSEC 记录存在但未验证"
			return info
		}
	}

	// 情况3：CD=0 查询失败，但 CD=1 查询成功
	if respCD1 != nil && errCD1 == nil {
		_, _, cd, tc := d.resolver.GetDNSSECFlags(respCD1)
		rcode := d.resolver.GetRcode(respCD1)

		info.CD = cd
		info.AD = false
		info.TC = tc
		info.Rcode = rcode

		// CD=0 失败可能是 Bogus 或网络问题
		info.State = googledns.DNSSECStateIndeterminate
		info.RiskLevel = googledns.DNSSECRiskDanger
		info.Message = "验证查询失败，可能存在 DNSSEC 问题"
		return info
	}

	// 默认：无法判定
	info.State = googledns.DNSSECStateIndeterminate
	info.RiskLevel = googledns.DNSSECRiskDanger
	info.Message = "无法确定 DNSSEC 状态"
	return info
}

// GetStateMessage 获取 DNSSEC 状态的中文说明
func GetStateMessage(state googledns.DNSSECState) string {
	switch state {
	case googledns.DNSSECStateSecure:
		return "DNSSEC 验证通过"
	case googledns.DNSSECStateInsecure:
		return "未启用 DNSSEC"
	case googledns.DNSSECStateBogus:
		return "DNSSEC 签名验证失败"
	case googledns.DNSSECStateIndeterminate:
		return "DNSSEC 状态未知"
	default:
		return "未知状态"
	}
}

// GetRiskLevelMessage 获取风险级别的中文说明
func GetRiskLevelMessage(level googledns.DNSSECRiskLevel) string {
	switch level {
	case googledns.DNSSECRiskNone:
		return ""
	case googledns.DNSSECRiskWarning:
		return "未启用 DNSSEC 签名，存在被劫持风险"
	case googledns.DNSSECRiskDanger:
		return "DNSSEC 异常，可能存在安全问题"
	default:
		return ""
	}
}

// FormatDNSSECMessage 格式化 DNSSEC 提示消息（用于附加到验证结果）
func FormatDNSSECMessage(info *googledns.DNSSECInfo) string {
	if info == nil || info.RiskLevel == googledns.DNSSECRiskNone {
		return ""
	}

	msg := fmt.Sprintf(" [DNSSEC: %s]", info.State)
	if info.Message != "" {
		msg = fmt.Sprintf(" [DNSSEC: %s - %s]", info.State, info.Message)
	}

	return msg
}
